﻿/**
 * Copyright (c) 2008 Justin Etheredge http://www.codethinked.com
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Microsoft Public License (Ms-PL)
 * which accompanies this distribution, and is available at
 * http://www.opensource.org/licenses/ms-pl.html
 * If redistributing this code, this entire header must remain intact.
 * 
 * Some of the code in this application has been taken 
 * from the following sources (all of which are licensed under
 * the Ms-PL):
 * Matt Warren's Blog: http://blogs.msdn.com/mattwar/
 * MSDN: http://msdn2.microsoft.com/en-us/library/bb546158.aspx
 */

using System;
using System.Linq;
using System.Linq.Expressions;
using LinqToSimpleDB.HelperClasses;

namespace LinqToSimpleDB
{
  public class SimpleDBQueryProvider : IQueryProvider
  {
    
    public string Domain { get; set; }
    public int Precision { get; set; }
    public int Scale { get; set; }

    private SimpleDBContext _context = null;

    internal SimpleDBQueryProvider()
    {
    }

    public SimpleDBQueryProvider(SimpleDBContext context)
    {
      if (context == null)
      {
        throw new ArgumentNullException("context");
      }
      this._context = context;
      this.Domain = context.DomainName;
      this.Precision = context.Precision;
      this.Scale = context.Scale;
    }

    public IQueryable CreateQuery(Expression expression)
    {
      Type elementType = TypeSystem.GetElementType(expression.Type);
      try
      {
        return (IQueryable)Activator.CreateInstance(typeof(Query<>).MakeGenericType(elementType), new object[] { this, expression });
      }
      catch (System.Reflection.TargetInvocationException tie)
      {
        throw tie.InnerException;
      }
    }

    // Queryable's collection-returning standard query operators call this method.
    public IQueryable<TResult> CreateQuery<TResult>(Expression expression)
    {
      return new Query<TResult>(this, expression);
    }

    public object Execute(Expression expression)
    {
      return SimpleDBQueryContext.Execute(_context, expression, Precision, Scale);
    }

    // Queryable's "single value" standard query operators call this method.
    // It is also called from QueryableTerraServerData.GetEnumerator().
    public TResult Execute<TResult>(Expression expression)
    {
      return (TResult)SimpleDBQueryContext.Execute(_context, expression, Precision, Scale);
    }

    public string GetQueryText(System.Linq.Expressions.Expression expression, int precision, int scale)
    {
      return SimpleDBQueryContext.GetQueryText(_context, expression, precision, scale);      
    }
  }
}
